package com.apobates.forum.toro.template.strategy;

import com.apobates.forum.toro.template.TemplateExpression;
import com.apobates.forum.toro.utils.BeanHelper;
import com.apobates.forum.toro.utils.CommonHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * 抽像模板映射器
 */
public abstract class AbstractTemplateStrategy {
    private final static Logger logger = LoggerFactory.getLogger(AbstractTemplateStrategy.class);
    /**
     * 标识子类的名称
     * @return
     */
    protected abstract String getSentinel();

    protected Map<String,String> getGroupObjAttr(Set<TemplateExpression> arguments) {
        return arguments.stream().collect(Collectors.toMap(arg->arg.getSelectAttr(), arg->arg.getSelectAttrTypeName()));
    }

    // 助手工具方法
    protected Map<String,Object> getGroupObjAttrVal(Object funArgVal, Function<String, ?> fun, Set<TemplateExpression> arguments) {
        // 1)获取需要获取的属性
        Map<String,String> tsObjAttrTypeMap = getGroupObjAttr(arguments);
        // 2)计算Member实例
        Object tsObjIns = fun.apply(funArgVal.toString());
        // 3)获取Member中需要聚合的属性及值
        Map<String,Object> tsObjAttrValMap = new HashMap<>();
        try {
            tsObjAttrValMap = BeanHelper.getMultiAttrVal(tsObjIns, tsObjAttrTypeMap);
        }catch (Exception e){
            logger.debug(String.format("[Template][%s]获取待聚合的属性名且值集合", getSentinel()));
        }
        // 4)设置Orders下的Member相关属性
        Map<String,Object> attrValMap = new HashMap<>();
        for(TemplateExpression te : arguments){
            // key = 设置target的属性, val = 设置的值
            attrValMap.put(te.getTargetAttr(), tsObjAttrValMap.get(te.getSelectAttr()));
        }
        return attrValMap;
    }

    // 助手工具方法
    protected Map<String,Object> getGroupObjAttrVal(String expectAttrName, Object expectVal, Collection<?> queryObjSet, Set<TemplateExpression> arguments) {
        // 1)计算集合中哪个是命中的
        Optional<?> tsObjIns = seekCollectionEle(expectAttrName, expectVal, queryObjSet);
        if(!tsObjIns.isPresent()){
            logger.debug(String.format("[Template][%s]从查询集合中筛选元素失败", getSentinel()));
            return Collections.emptyMap();
        }
        // print log:
        // logger.debug("[Template][Batch-S]命中元素："+tsObjIns.get());
        // 2)获取需要获取的属性
        Map<String,String> tsObjAttrTypeMap = getGroupObjAttr(arguments);
        // print log:
        // Set<String> getAttrTypes = tsObjAttrTypeMap.values().stream().collect(Collectors.toSet());
        // logger.debug(String.format("[Template][Batch-S]获取待聚合的属性集合, 属生：%s, 类型: %s", String.join(",", tsObjAttrTypeMap.keySet()), getAttrTypes));
        // 3)获取Member中需要聚合的属性及值
        Map<String,Object> tsObjAttrValMap = new HashMap<>();
        try {
            tsObjAttrValMap = BeanHelper.getMultiAttrVal(tsObjIns.get(), tsObjAttrTypeMap);
        }catch (Exception e){
            logger.debug(String.format("[Template][%s]获取待聚合的属性名且值集合", getSentinel()));
        }
        // print log:
        // Set<String> getAttrVals = tsObjAttrValMap.values().stream().map(Object::toString).collect(Collectors.toSet());
        // logger.debug(String.format("[Template][Batch-S]获取待聚合的属性集合, 属生：%s, 值: %s", String.join(",", tsObjAttrValMap.keySet()), getAttrVals));
        // 4)设置Orders下的Member相关属性
        Map<String,Object> attrValMap = new HashMap<>();
        for(TemplateExpression te : arguments){
            // key = 设置target的属性, val = 设置的值
            attrValMap.put(te.getTargetAttr(), tsObjAttrValMap.get(te.getSelectAttr()));
        }
        // print log:
        // Set<String> setAttrVals = attrValMap.values().stream().map(Object::toString).collect(Collectors.toSet());
        // logger.debug(String.format("[Template][Batch-S]返回聚合的属性名: %s, 值：%s", String.join(",", attrValMap.keySet()), setAttrVals));
        return attrValMap;
    }

    // 从候选集合中搜索期待的元素
    protected Optional<?> seekCollectionEle(String expectAttrName, Object expectVal, Collection<?> result) {
        return CommonHelper.seekFirstEle(result, expectAttrName, expectVal);
    }

    // 设置targetObj中聚合的属性
    protected <T,U> void setMultiAttrVal(T targetObj, U refObj, String joinAttr, String linkAttr, String groupName, Collection<?> queryObjSet, Set<TemplateExpression> arguments) {
        Map<String,Object> attrValMap = getGroupObjAttrVal(
                linkAttr,
                BeanHelper.getAttrVal(refObj, joinAttr),
                queryObjSet,
                arguments);
        try {
            if(!attrValMap.isEmpty()) {
                BeanHelper.setMultiAttrVal(targetObj, attrValMap);
            }
        }catch (Exception e){
            logger.debug(String.format(
                    "[Template][%s]设置%s的%s属性失败. 汲及属集数量",
                    getSentinel(),
                    targetObj.getClass().getSimpleName(),
                    groupName,
                    attrValMap.size()));
        }
    }
}
